import { BadRequestException, Controller, Get, Headers, HttpException, HttpStatus, Inject, Query, UnauthorizedException } from '@nestjs/common';
import { AppService } from './app.service';
import { randomUUID } from 'crypto';
import * as qrcode from 'qrcode';
import { JwtService } from '@nestjs/jwt';

const map = new Map<string, QrCodeInfo>();

interface QrCodeInfo{
  status: 'noscan' | 'scan-wait-confirm' | 'scan-confirm' | 'scan-cancel' | 'expired',
  userInfo?: {
    userId: number;
  }
}
// noscan 未扫描
// scan-wait-confirm -已扫描，等待用户确认
// scan-confirm 已扫描，用户同意授权
// scan-cancel 已扫描，用户取消授权
// expired 已过期


@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Inject(JwtService)
  private jwtService: JwtService;

  private users = [
      {id: 1, username: 'newking', password: 'zjhQQsybzd'},
      {id: 2, username: 'newking123', password: 'zjhQQsybzd'},
  ];


  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get('qrcode/generate')
  async generate(){
     const uuid = randomUUID();
     const dataUrl = await qrcode.toDataURL(`http://192.168.0.221:3000/pages/confirm.html?id=${uuid}`);

     //在redis保存一份,点击登录改变状态，同时轮询某个接口,判断是否状态改变
     map.set(`qrcode_${uuid}`, {
      status: 'noscan'
     });
    
     return {
      qrcode_id: uuid,
      img: dataUrl
     }
  }

  @Get('qrcode/check')
  async check(@Query('id') id:string){
    return map.get(`qrcode_${id}`);
  }

@Get('qrcode/scan')
async scan(@Query('id') id: string) {
    const info = map.get(`qrcode_${id}`);
    if(!info) {
      throw new BadRequestException('二维码已过期');
    }
    console.log(info);
    info.status = 'scan-wait-confirm';
    return 'success';
}

@Get('qrcode/confirm')
//@Req() 装饰器用于获取整个请求对象，包括请求头、请求体、请求参数等所有请求信息
//@Headers('Authorization') 装饰器则用于获取请求头中指定字段的值。
async confirm(@Query('id') id: string,@Headers('Authorization') auth: string) {
  
    let user;     
    //先判断手机端有没有登录信息（模拟手机app端的逻辑）
    try{
      const [, token] = auth.split(' ');
      const info = await this.jwtService.verify(token);
    
      //find 查出匹配成功的单条完整数据
      user = this.users.find(item => item.id == info.userId);
    } catch(e) {
      throw new HttpException('token 过期，请重新登录',HttpStatus.BAD_REQUEST);
    }

    const info = map.get(`qrcode_${id}`);
    if(!info) {
      throw new BadRequestException('二维码已过期');
    }

    if(info.status === 'scan-cancel'){
      throw new BadRequestException('已取消');
    }

    if(info.status === 'scan-confirm'){
      throw new BadRequestException('已登录');
    }

    info.status = 'scan-confirm';
    info.userInfo = user;


    return info;
}

@Get('qrcode/cancel')
async cancel(@Query('id') id: string) {
    const info = map.get(`qrcode_${id}`);
    if(!info) {
      throw new BadRequestException('二维码已过期');
    }
    info.status = 'scan-cancel';
    return 'success';
}




@Get('login')
async login(@Query('username') username: string, @Query('password') password: string) {

  const user = this.users.find(item => item.username === username);

  if(!user) {
    throw new UnauthorizedException('用户不存在');
  }
  if(user.password !== password) {
    throw new UnauthorizedException('密码错误');
  }

  return {
      token: await this.jwtService.sign({
      userId: user.id
   })
  }

}


  @Get('userInfo')
  async userInfo(@Headers('Authorization') auth: string) {
      try{
        const [, token] = auth.split(' ');
        const info = await this.jwtService.verify(token);

        const user = this.users.find(item => item.id == info.userId);
        return user;
      } catch(e) {
        throw new UnauthorizedException('token 过期，请重新登录');
      }
  }



}
